#include "drawthread.h"
#include <QPainter>
#include <QVariantList>
#include <QFile>
#include <QApplication>
#include <QEvent>
#include <QPaintEvent>
#include <QImageReader>

DrawThread::DrawThread(QString picturesHome, QMap<PictureItem::ImageSizes,QStringList> resolutions) :
    m_picturesHome(picturesHome),
    m_resolutions(resolutions),
    m_success(false),
    m_final(NULL),
    m_requestStop(false)
{
    qDebug() << __PRETTY_FUNCTION__;
    m_combiner = new QPainter();
}

DrawThread::~DrawThread()
{
    qDebug() << __PRETTY_FUNCTION__;
    if(m_final)
        delete m_final;
    if(m_combiner)
        delete m_combiner;
}

void DrawThread::createImage(PictureItem::ImageTypes imageType, PictureItem::ImageSizes imageSize, QVariantList imageList, QString fileName, QColor background, QColor backgroundOld, int margin, int aspectRatio)
{
    qDebug() << __PRETTY_FUNCTION__;
    m_imageType = imageType;
    m_imageSize = imageSize;
    m_imageList = imageList;
    m_fileName = fileName;
    m_background = background;
    m_backgroundOld = backgroundOld;
    m_margin = margin;    
    m_aspect = aspectRatio;
    start();
}

void DrawThread::run()
{
    qDebug() << __PRETTY_FUNCTION__ << " imageType: " << m_imageType << " imageSize: " << m_imageSize << " filename: " << m_fileName << " color: " << m_background << " margin: " << m_margin;
    int watermarkMargin = 0;

    if(!m_margin)
        watermarkMargin = Margin;

    if(!m_fileName.startsWith(m_picturesHome))
        m_fileName = m_picturesHome+m_fileName;
    if(!m_fileName.endsWith(".jpg",Qt::CaseInsensitive))
        m_fileName.append(".jpg");

    QFile tmp(m_fileName);
    if(tmp.exists(m_fileName))
        tmp.remove();

    int scaledWidth = m_resolutions[m_imageSize].at(0).toInt();
    int scaledHeight = m_resolutions[m_imageSize].at(1).toInt();

    QSize biggestSize;
    QList<QImage*> scaledList;
    for(int i=0;i<m_imageList.count();i++){
        scaledList.append(scaledImage(i));
        if(scaledList.last()->size().height()>biggestSize.height()||
                scaledList.last()->size().width()>biggestSize.width())
            biggestSize = scaledList.last()->size();
    }
    if(biggestSize.width()<scaledWidth)
        scaledWidth = biggestSize.width();
    if(biggestSize.height()<scaledHeight)
        scaledHeight = biggestSize.height();

    if(!m_imageList.isEmpty()){
        int currentHeight = m_margin;
        int currentWidth = m_margin;

        switch(m_imageType){
        case PictureItem::Tile2by2:{
            qDebug() << "Tile" << scaledWidth*2+(2*m_margin+m_margin)<<" x "<<scaledHeight*2+(2*m_margin+m_margin)+watermarkMargin;

            m_final = new QImage(scaledWidth*2+(2*m_margin+m_margin),scaledHeight*2+(2*m_margin+m_margin)+watermarkMargin,IMAGE_FORMAT);
            qDebug() << "m_final: " <<m_final->isNull();
            m_combiner->begin(m_final);
            m_combiner->fillRect(QRect(0,0,m_final->width(),m_final->height()),m_background);

            for(int i=0;i<m_imageList.count()/2;i++){
                if(m_requestStop)
                    break;

                int deltaX = scaledWidth-scaledList.at(i)->size().width();
                int deltaY = scaledHeight-scaledList.at(i)->size().height();

                if(deltaX){
                    deltaX = deltaX/2;
                }
                if(deltaY){
                    deltaY = deltaY/2;
                }

                m_combiner->drawImage(QPoint(currentWidth+deltaX,currentHeight+deltaY),*scaledList.at(i));
                currentWidth+=scaledWidth+m_margin;
            }
            currentWidth=m_margin;
            currentHeight+=scaledHeight+m_margin;
            for(int i=m_imageList.count()/2;i<m_imageList.count();i++){
                if(m_requestStop)
                    break;

                int deltaX = scaledWidth-scaledList.at(i)->size().width();
                int deltaY = scaledHeight-scaledList.at(i)->size().height();

                if(deltaX){
                    deltaX = deltaX/2;
                }
                if(deltaY){
                    deltaY = deltaY/2;
                }

                m_combiner->drawImage(QPoint(currentWidth+deltaX,currentHeight+deltaY),*scaledList.at(i));
                currentWidth+=scaledWidth+m_margin;
            }
            m_combiner->end();
        }break;

        case PictureItem::Side:{
            qDebug() << "Sideways: " << scaledWidth*m_imageList.count()+(2*m_margin+m_margin*(m_imageList.count()-1))<< " x " <<scaledHeight+(2*m_margin)+watermarkMargin;
            int totalWidth = 0;
            foreach(QImage* i,scaledList){
                totalWidth+=i->size().width();
            }
            qDebug() << "totalWidth: " << totalWidth;

            //m_final = new QImage(scaledWidth*m_imageList.count()+(2*m_margin+m_margin*(m_imageList.count()-1)),scaledHeight+(2*m_margin)+watermarkMargin,IMAGE_FORMAT);
            m_final = new QImage(totalWidth+(2*m_margin+m_margin*(m_imageList.count()-1)),scaledHeight+(2*m_margin)+watermarkMargin,IMAGE_FORMAT);
            qDebug() << "m_final: " <<m_final->isNull();
            m_combiner->begin(m_final);
            m_combiner->fillRect(QRect(0,0,m_final->width(),m_final->height()),m_background);

            for(int i=0;i<m_imageList.count();i++){
                if(m_requestStop)
                    break;

                int deltaX = scaledWidth-scaledList.at(i)->size().width();
                int deltaY = scaledHeight-scaledList.at(i)->size().height();

                if(deltaY){
                    deltaY = deltaY/2;
                }

                m_combiner->drawImage(QPoint(currentWidth,currentHeight+deltaY),*scaledList.at(i));
                currentWidth+=scaledWidth+m_margin-deltaX;
            }
            m_combiner->end();
        }break;

        case PictureItem::UpDown:{
            qDebug() << "Down" << scaledWidth+(2*m_margin) << " x " << scaledHeight*m_imageList.count()+(2*m_margin+m_margin*(m_imageList.count()-1))+watermarkMargin;
            int totalHeight = 0;
            foreach(QImage* i,scaledList){
                totalHeight+=i->size().height();
            }
            qDebug() << "totalHeight: " << totalHeight;

            m_final = new QImage(scaledWidth+(2*m_margin),totalHeight+(2*m_margin+m_margin*(m_imageList.count()-1))+watermarkMargin,IMAGE_FORMAT);
            qDebug() << "m_final: " <<m_final->isNull();
            m_combiner->begin(m_final);
            m_combiner->fillRect(QRect(0,0,m_final->width(),m_final->height()),m_background);

            for(int i=0;i<m_imageList.count();i++){
                if(m_requestStop)
                    break;

                int deltaX = scaledWidth-scaledList.at(i)->size().width();
                int deltaY = scaledHeight-scaledList.at(i)->size().height();

                if(deltaX){
                    deltaX = deltaX/2;
                }

                m_combiner->drawImage(QPoint(currentWidth+deltaX,currentHeight),*scaledList.at(i));
                currentHeight+=scaledHeight+m_margin-deltaY;
            }
            m_combiner->end();
        }break;

        default:break;
        }
    }

    while(!scaledList.isEmpty()){
        delete scaledList.takeLast();
    }

    // watermark
    if(!m_final->isNull() && !m_requestStop){
        qDebug() << "insert watermark";
        QSize size = m_final->size();
        QFont font = QApplication::font();
        QRect rect(0,0,size.width(),size.height());
        rect.setHeight(QFontMetrics(font).height());
        rect.moveTopLeft(QPoint(0,size.height()-rect.height()));

        m_combiner->begin(m_final);
        m_combiner->fillRect(rect,m_background);
        m_combiner->drawImage(QPoint(0,0),*m_final);
        if(m_background == Qt::black)
            m_combiner->setPen(Qt::white);
        else
            m_combiner->setPen(Qt::black);
        m_combiner->drawText(rect,Qt::AlignRight, APP_NAME);
        m_combiner->setPen(Qt::NoPen);
        m_combiner->drawRect(rect);
        m_combiner->end();

        bool save = m_final->save(m_fileName);
        qDebug() << "save: " << save << " : " <<m_final->isNull() << " fn: " << m_fileName;
        if(save && !m_final->isNull())
            m_success = true;
    }
}

QImage* DrawThread::scaledImage(int index)
{
    qDebug() << __PRETTY_FUNCTION__;
    QUrl fileUrl(m_imageList[index].toString());    
    QImage* img = new QImage;
    int w = m_resolutions[m_imageSize].at(0).toInt();
    int h = m_resolutions[m_imageSize].at(1).toInt();

    QFile file(fileUrl.toLocalFile());
    if(file.open(QIODevice::ReadOnly)){        
        QScopedPointer<QImageReader> reader(new QImageReader(&file));
        QSize imgsize;
        imgsize.scale(QSize(w,h),(Qt::AspectRatioMode)m_aspect);

        if(reader->size().width()>w && reader->size().height()>h)
            reader->setScaledSize(imgsize);

        if(!reader->read(img)){
            qDebug() << "error: " << reader->error() << " str: " << reader->errorString();
            m_success = false;
            m_requestStop = true;
        }
        qDebug() << "img aspect: " << img->size();
    }
    file.close();

    return img;
}

void DrawThread::stopWorking()
{
    qDebug() << __PRETTY_FUNCTION__;
    m_requestStop = true;
}

bool DrawThread::stopRequested()
{
    qDebug() << __PRETTY_FUNCTION__ << " val: " << m_requestStop;
    return m_requestStop;
}

QString DrawThread::filename()
{
    qDebug() << __PRETTY_FUNCTION__;
    return m_fileName;
}
